import json
import datetime
from package.connector.redis_db import rdb
from package.fastapi.cache import Cache


class ConfigureCache(Cache):
    Prefix = 'system:configure'

    def get(self, name):
        cache = rdb.redis.get(f'{self.Prefix}:{name}')
        return json.loads(cache)

    def set(self, name, value):
        rdb.redis.set(f'{self.Prefix}:{name}', json.dumps(value))
        return


class TempUserLockCache(Cache):
    """临时锁定"""
    Prefix = 'system:lock'
    Category = 'user'

    def get(self, current_ts=None):
        if not current_ts:
            current_ts = int(datetime.datetime.utcnow().timestamp() * 1000)
        return [item.decode() for item in
                rdb.redis.zrangebyscore(f'{self.Prefix}:{self.Category}', min=current_ts, max=4102416000000)]

    def set(self, key, current_ts, lock_ts):
        rdb.redis.zremrangebyscore(f'{self.Prefix}:{self.Category}', min=0, max=current_ts)
        rdb.redis.zadd(f'{self.Prefix}:{self.Category}', {key: current_ts + lock_ts})
        return

    def delete(self, key):
        """解除锁定
        """
        rdb.redis.zrem(f'{self.Prefix}:{self.Category}', key)
        fail_auth_cache.delete(key)


class TempIpLockCache(TempUserLockCache):
    """临时锁定"""
    Category = 'ip'


class FailAuthCache(Cache):
    """认证失败 窗口次数"""
    Prefix = 'system:fail_auth'

    def set(self, name, ex=180):
        times = rdb.redis.incr(f'{self.Prefix}:{name}')
        rdb.redis.expire(f'{self.Prefix}:{name}', ex)
        return times

    def delete(self, name):
        rdb.redis.delete(f'{self.Prefix}:{name}')


class AutoDetectCache(Cache):
    """自动发现数据源 缓存
    """
    Prefix = 'collector:auto_detect'

    def get(self):
        return rdb.redis.smembers(self.Prefix)

    def set(self, *value):  # 可能是批量添加
        return rdb.redis.sadd(self.Prefix, *value)

    def delete(self, value):
        rdb.redis.srem(self.Prefix, value)


class ReadOnlyIndexCaculatedCache(Cache):
    """索引是否已经执行过计算任务
    """
    Prefix = 'collector:readonly_index:caculated'

    def get(self):
        return rdb.redis.smembers(self.Prefix)

    def set(self, *value):  # 可能是批量添加
        return rdb.redis.sadd(self.Prefix, *value)

    def delete(self, value):
        rdb.redis.srem(self.Prefix, value)


class WriteIndexCache(Cache):
    """自动发现数据源 缓存
    """
    Prefix = 'collector:write_index'

    def get(self, model_id=None):
        """抑制次数"""
        if model_id:
            data = rdb.redis.hget(self.Prefix, model_id)
            return data.decode() if data else None
        
        data = rdb.redis.hgetall(self.Prefix)
        return {k.decode(): v.decode() for k, v in data.items()}

    def set(self, kwargs):
        return rdb.redis.hmset(f'{self.Prefix}', kwargs)
    
    def delete(self, *ids):
        rdb.redis.hdel(f'{self.Prefix}', *ids)


class SourceINtimeCache(Cache):
    """数据源 实时进入数据量统计
    """
    Prefix = 'collector:source:intime:'

    def get(self, id):
        """"""
        count = rdb.redis.get(f'{self.Prefix}{id}')
        return int(count) if count else 0

    def set(self, id, value, ex):
        return rdb.redis.set(f'{self.Prefix}{id}', value, ex=ex)
    
    def delete(self, id):
        rdb.redis.delete(f'{self.Prefix}{id}')


class AlertSupressCache(Cache):
    """图表缓存数据
    """
    Prefix = 'analyzer:alert:supress:'

    def get(self, id):
        """抑制次数"""
        count = rdb.redis.get(f'{self.Prefix}{id}')
        if not count:
            return 0
        return int(count)

    def incr(self, id):
        return rdb.redis.incr(f'{self.Prefix}{id}')

    def set(self, id, ex):
        return rdb.redis.set(f'{self.Prefix}{id}', 0, ex=ex)
    
    def delete(self, id):
        rdb.redis.delete(f'{self.Prefix}{id}')


class NotifyCache(Cache):
    """通告缓存数据
    """
    Prefix = 'system:notify:cache'

    def get(self, id=None):
        """抑制次数"""
        if id:
            data = rdb.redis.hget(self.Prefix, id) or '{}'
            return json.loads(data)
        data = rdb.redis.hgetall(self.Prefix)
        return {k.decode(): json.loads(v) for k, v in data.items()}

    def set(self, kwargs):
        return rdb.redis.hmset(f'{self.Prefix}', kwargs)
    
    def delete(self, *ids):
        rdb.redis.hdel(f'{self.Prefix}', *ids)


configure_cache = ConfigureCache()
temp_userlock_cache = TempUserLockCache()
temp_iplock_cache = TempIpLockCache()
fail_auth_cache = FailAuthCache()

auto_detect_cache = AutoDetectCache()
write_index_cache = WriteIndexCache()
readonly_index_caculated_cache = ReadOnlyIndexCaculatedCache()
source_intime_cache = SourceINtimeCache()

alert_supress_cache = AlertSupressCache()

notify_cache = NotifyCache()
